1   /************************************************************
2   *                     Copyright                            *
3   * Portions of this software are Copyright (c) 1993 - 2002, *
4   * Chad Z. Hower (Kudzu) and the Indy Pit Crew              *
5   *  - http://www.nevrona.com/Indy/                          *
6   ************************************************************/
7   
8   /************************************************************
9   *                     Copyright                            *
10  * Portions of this software are Copyright (c) 1993 - 2002, *
11  * Chad Z. Hower (Kudzu) and the Indy Pit Crew              *
12  *  - http://www.nevrona.com/Indy/                          *
13  ************************************************************/
14  package org.indy;
15  
16  import java.util.ArrayList;
17  import java.util.Collection;
18  import java.util.Collections;
19  import java.util.Iterator;
20  
21  
22  /***
23   *  Provides the basis for Indy threading as used by {@link PeerThread} in {@link TCPServer}.
24   *
25   *
26   *@author    OTG
27   *@version  1.0
28   *@see StopMode
29   *@see Priority
30   */
31  public abstract class IndyThread implements Runnable {
32    /***
33     *
34     */
35    private Priority priority = Priority.NORMAL;
36  
37    /***
38     *
39     */
40    private StopMode stopMode = StopMode.TERMINATE;
41  
42    /***
43     *
44     */
45    private volatile Exception terminatingException;
46  
47    /***
48     *
49     */
50    private volatile boolean stopped = true;
51  
52    /***
53     *
54     */
55    private volatile boolean terminated = false;
56  
57    /***
58     *
59     */
60    private final Object suspendLock = new Object();
61  
62    /***
63     *
64     */
65    protected final Thread threadImpl = new IndyThreadImpl();
66  
67    /***
68     *
69     */
70    private final ArrayList threadListeners = new ArrayList();
71  
72    /***
73     *  Description of the Field
74     */
75    protected volatile boolean stopRequested;
76  
77    /***
78     *  Constructor for the IdThread object
79     */
80    public IndyThread() {
81    }
82  
83    /***
84     *  Gets the stopped attribute of the IdThread object
85     *
86     *@return    The stopped value
87     */
88    public boolean isStopped() {
89      return stopped;
90    }
91  
92    /***
93     *
94     * @return
95     */
96    protected Thread getThreadImpl() {
97      return threadImpl;
98    }
99  
100   /***
101    *  Description of the Method
102    */
103   public final void start() {
104     if (terminated) {
105       throw new IllegalStateException();
106     }
107 
108     if (!threadImpl.isAlive()) {
109       threadImpl.start();
110     }
111     else if (stopped) {
112       resume();
113     }
114 
115     stopped = false;
116   }
117 
118   /***
119    *  Description of the Method
120    */
121   public final void stop() {
122     if (!stopped) {
123       if (stopMode == StopMode.TERMINATE) {
124         terminate();
125       }
126 
127       stopped = true;
128     }
129   }
130 
131   /***
132    *
133    */
134   public void terminate() {
135     stopped = true;
136     terminated = true;
137     resume();
138   }
139 
140   /***
141    *
142    */
143   private void resume() {
144     synchronized (suspendLock) {
145       suspendLock.notifyAll();
146     }
147   }
148 
149   /***
150    *
151    * @throws InterruptedException
152    */
153   private void suspend() throws InterruptedException {
154     synchronized (suspendLock) {
155       suspendLock.wait();
156     }
157   }
158 
159   /***
160    *  Description of the Method
161    *
162    *@throws  InterruptedException  Description of the Exception
163    */
164   public void join() throws InterruptedException {
165     threadImpl.join();
166   }
167 
168   /***
169    *  Description of the Method
170    *
171    *@throws  InterruptedException  Description of the Exception
172    */
173   public void terminateAndWait() throws InterruptedException {
174     terminate();
175     join();
176   }
177 
178   /***
179    *
180    * @return
181    */
182   public StopMode getStopMode() {
183     return stopMode;
184   }
185 
186   /***
187    *
188    * @param mode
189    */
190   public void setStopMode(StopMode mode) {
191     stopMode = mode;
192   }
193 
194   /***
195    *
196    * @return
197    */
198   public Priority getPriority() {
199     //return priority;
200     return Priority.parse(threadImpl.getPriority());
201   }
202 
203   /***
204    *
205    * @param p
206    */
207   public void setPriority(Priority p) {
208     priority = p;
209 
210     if (!terminated) {
211       threadImpl.setPriority(p.num);
212     }
213   }
214 
215   /***
216    *
217    */
218   protected void cleanup() throws InterruptedException {
219   }
220 
221   /***
222    *  Description of the Method
223    */
224   protected void beforeRun() throws InterruptedException {
225   }
226 
227   /***
228    *  Description of the Method
229    */
230   protected void afterRun() throws InterruptedException {
231   }
232 
233   /***
234    *  Description of the Method
235    */
236   protected void beforeExecute() throws InterruptedException {
237   }
238 
239   /***
240    *  Description of the Method
241    */
242   protected void afterExecute() throws InterruptedException {
243   }
244 
245   /***
246    *  Adds a feature to the ThreadListener attribute of the IdThread object
247    *
248    *@param  l  The feature to be added to the ThreadListener attribute
249    */
250   public void addThreadListener(IndyThreadListener l) {
251     synchronized (threadListeners) {
252       if (!threadListeners.contains(l)) {
253         threadListeners.add(l);
254       }
255     }
256   }
257 
258   /***
259    *
260    * @param l
261    */
262   public void removeThreadListener(IndyThreadListener l) {
263     threadListeners.remove(l);
264   }
265 
266   /***
267    *
268    */
269   private void doStopped() {
270     Collection l = null;
271 
272     //don't want to block the list for the entire iteration (which could take any amount of time)
273     synchronized (threadListeners) {
274       l = Collections.unmodifiableCollection(threadListeners);
275     }
276 
277     IndyThreadEvent evt = new IndyThreadEvent(this);
278 
279     Iterator i = l.iterator();
280 
281     while (i.hasNext()) {
282       ((IndyThreadListener) i.next()).onStopped(evt);
283     }
284   }
285 
286   /***
287    *
288    */
289   private void doException() {
290     Collection l = null;
291 
292     //don't want to block the list for the entire iteration (which could take any amount of time)
293     synchronized (threadListeners) {
294       l = Collections.unmodifiableCollection(threadListeners);
295     }
296 
297     IndyThreadEvent evt = new IndyThreadEvent(this);
298 
299     Iterator i = l.iterator();
300 
301     while (i.hasNext()) {
302       ((IndyThreadListener) i.next()).onException(evt);
303     }
304   }
305 
306   /***
307    * An enumertaed class describing the possible stopping modes for an IndyThread.
308    *
309    * <code>TERMINATE</code> means that any call to stop will terminate the thread, and the IndyThread instance will be unuseable.
310    * <code>SUSPEND</code> means that the thread will pause and can be restarted.
311    *
312    * @author OTG
313    * @version 1.0
314    * @see IndyThread
315    */
316   public static class StopMode {
317     /***
318      * Used to signal that the enclosing <code>IndyThread</code> should terminate when stop is called.
319      *
320      * @see IndyThread#stop()
321      */
322     public static final StopMode TERMINATE = new StopMode("Terminate");
323 
324     /***
325      * Used to signal that the enclosing <code>IndyThread</code> should suspend when stop is called.
326      *
327      * @see IndyThread#stop()
328      */
329     public static final StopMode SUSPEND = new StopMode("Suspend");
330 
331     /***
332      * A string representation of this <code>StopMode</code>
333      */
334     private final String friendlyName;
335 
336     /***
337      * Constructs a new <code>StopMode</code>; private to prevent inheritence.
338      *
339      * @param friendlyName The string representation of this <code>StopMode</code>
340      */
341     private StopMode(String friendlyName) {
342       this.friendlyName = friendlyName;
343     }
344 
345     /***
346      * Returns a string representation of this <code>StopMode</code> as a friendly name.
347      *
348      * @return A user friendly string for this <code>StopMode</code>
349      */
350     public String toString() {
351       return friendlyName;
352     }
353   }
354 
355   /***
356    * Represents IndyThread priority.
357    *
358    *
359    */
360   public static class Priority {
361     /***
362      *
363      */
364     public static final Priority MIN = new Priority(Thread.MIN_PRIORITY);
365 
366     /***
367      *
368      */
369     public static final Priority NORMAL = new Priority(Thread.NORM_PRIORITY);
370 
371     /***
372      *
373      */
374     public static final Priority MAX = new Priority(Thread.MAX_PRIORITY);
375 
376     /***
377      *
378      */
379     private final int num;
380 
381     /***
382      *
383      * @param num
384      */
385     private Priority(int num) {
386       this.num = num;
387     }
388 
389     public static Priority parse(int value) {
390       System.err.println(value);
391 
392       switch (value) {
393         case 1:
394         case 2:
395         case 3:
396           return MIN;
397 
398         case 4:
399         case 5:
400         case 6:
401           return NORMAL;
402 
403         case 7:
404         case 8:
405         case 9:
406         case 10:
407           return MAX;
408 
409         default:
410           throw new IllegalArgumentException(
411               "Not a valid thread priority value (1..10)");
412       }
413     }
414   }
415 
416   /***
417    *
418    * <p>Title: </p>
419    * <p>Description: </p>
420    * <p>Copyright: Copyright (c) 2002</p>
421    * <p>Company: </p>
422    * @author unascribed
423    * @version 1.0
424    */
425   private class IndyThreadImpl extends Thread {
426     public void run() {
427       try {
428         try {
429           beforeExecute();
430 
431           while (!terminated) {
432             if (stopped) {
433               doStopped();
434 
435               if (stopped) {
436                 if (terminated) {
437                   break;
438                 }
439 
440                 IndyThread.this.suspend();
441 
442                 if (terminated) {
443                   break;
444                 }
445               }
446 
447               //if stopped inner
448             }
449 
450             //if stopped outer
451             try {
452               beforeRun();
453 
454               try {
455                 while (!stopped) {
456                   IndyThread.this.run();
457                 }
458               }
459                finally {
460                 afterRun();
461               }
462             }
463              finally {
464               cleanup();
465             }
466           }
467 
468           //while !terminated
469         }
470 
471         //tryf
472          finally {
473           afterExecute();
474         }
475       }
476 
477       //tryc
478        catch (Exception e) {
479         terminatingException = e;
480         doException();
481         terminate();
482       }
483     }
484   }
485 
486   //inner class
487 }
This page was automatically generated by Maven